/*
 * @(#)asnrt.h
 *
 * Copyright (c) 2009-2013, Shannon Information Co., Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 	1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 	2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 	3. Neither the name of Shannon Information nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#ifndef ASNRT_H_
#define ASNRT_H_

#include "stdlib.h"
#include "setjmp.h"
#include "string.h"

#ifdef __cplusplus
extern "C" {
#endif

#define		ASNRT_VERSION		"v3.14.15.r20140101"

/* C values types for ASN.1 values */

#ifdef _MSC_VER /* VS */
	typedef __int64 xlong;
	typedef unsigned __int64 uxlong;
#else
	#ifdef __C51__ /* C51 */
		typedef long xlong;
		unsigned long uxlong;
	#else /* Unix */
		typedef long long xlong;
		typedef unsigned long long uxlong;
	#endif
#endif

#define BI_SIZE 16
#define BI_BITS 4/* [log2(BI_SIZE)] */

/**
 * The two's-complement representation of Big Integer
 * Byte[0] Byte[1]  ..  Byte     [n-1]	Byte[size-1]
 * B7..B0  B15..B8  ..  B8n-1..B8(n-1)  XXXXXXXXXXXX
 */
typedef char BigInteger[BI_SIZE];

#ifndef false
#define	false	0
#endif
#ifndef true
#define	true	1
#endif

#ifndef ASNRT_BOOLEAN
#define ASNRT_BOOLEAN
typedef unsigned char boolean;
#endif

typedef struct {
	/* number of bits */
    unsigned int length;
    char*  bytes;
} Bits;

typedef struct {
	/* number of bytes */
    unsigned int length;
    char*  bytes;
} Octets;

typedef struct {
    unsigned int length;
    unsigned int* ids;
} Oid;

typedef unsigned short wchar;

typedef unsigned int uchar;

typedef struct {
    signed int year; /* 0~9999 */
    signed char month; /* Jun = 1, ..., Dec = 12 */
    signed char day; /* 1~31 */
    signed char hour; /* 0~23 */
    signed char minute; /* 0~59 */
    signed char second; /* 0~59 */

    /* hour offset from UTC. For example, hour_offset=8 means eight hours ahead of GMT */
    signed char hour_offset;

    /* minute offset from UTC. For example, minute_offset=15 means 15 minutes ahead of GMT */
    signed char minute_offset;

    signed int millisec; /* 0~999 */
} Time;

#define List(E)				\
struct {					\
	unsigned int capacity;	\
	unsigned int size;		\
	E* elements;			\
}

/**
 * @return -1, 0 or 1 as this a is numerically less than, equal
 *         to, or greater than {@code b}.
 */
int compareBigint(BigInteger a, BigInteger b);

/**
 *  a++
 */
void incrBigint(BigInteger a);

/**
 *  a--
 */
void decrBigint(BigInteger a);

/**
 *  c = a + b
 */
void addBigint(BigInteger a, BigInteger b, BigInteger c);

/**
 *  c = a - b
 */
void subBigint(BigInteger a, BigInteger b, BigInteger c);

/**
 *  The number of effective octets for unsigned number
 */
int numOfEffectiveOctets(BigInteger a);

/**
 *  The number of effective bytes for signed number
 */
int numOfEffectiveBytes(BigInteger a);


#define FILLOC_BITS(bits, bs, size) (\
	bits.length = ((size-1)/8)+1,\
	bits.bytes = ASN_ALLOC(bits.length, char),\
	bits.bytes==NULL? NULL:(asn_memcpy(bits.bytes, bs, bits.length), bits.bytes))

Bits* wrapBits(char* bytes, unsigned int length);

Octets* wrapOctets(char* bytes, unsigned int length);

#define FILLOC_OCTETS(octets, bs, size) (\
	octets.length = size,\
	octets.bytes = ASN_ALLOC(octets.length, char),\
	octets.bytes==NULL? NULL:(asn_memcpy(octets.bytes, bs, octets.length), octets.bytes))

boolean isBitSet(Bits* bits, unsigned int b);
void setBit(Bits* bits, unsigned int b);
void clearBit(Bits* bits, unsigned int b);

unsigned int cstrlen(char* s);
unsigned int wstrlen(wchar* s);
unsigned int ustrlen(uchar* s);

/**
 *  Macro to allocate and fill a string.
 */
#define FILLOC_STRINGS(string, str, size) (\
	string = ASN_ALLOC(size+1, char),\
	string==NULL? NULL:(asn_memcpy(string, str, size), string))

/**
 *  Macro to allocate a list with capacity and size of nitem.
 */
#define ALLOC_LIST(list, nitem) (\
		list.capacity = nitem,\
		list.size = nitem,\
		list.elements = ASN_ALLOC(nitem, typeof(*list.elements)) )

/* The encoding rules */

#define		BASIC_ENCODING_RULES             0
#define		CANONICAL_ENCODING_RULES         1
#define		DISTINGUISHED_ENCODING_RULES     2
#define		UNALIGNED_PACKED_ENCODING_RULES  3
#define		ALIGNED_PACKED_ENCODING_RULES    4
#define		A_XDR_ENCODING_RULES             64

/* The metadata type */

struct AsnCodec;

typedef struct {
	const struct AsnCodec* codec;
	const void*  config;
} AsnType;

typedef struct TraceStack {
	void* object;
	AsnType* type;
	struct TraceStack* next;
} TraceStack;

/* The buffer context */

typedef	struct {
	jmp_buf	jumper;
	char* file_name;
	int line_number;
	unsigned long position;
	int extval;
	void* trace;
	TraceStack stack;
} AsnContext;

struct AsnInputStream;
struct AsnOutputStream;

/* The working buffer */
typedef struct {
	struct AsnInputStream* in;
	struct AsnOutputStream* out;
	char* array;
	unsigned long position;
	unsigned long capacity;
	unsigned long limit;
	boolean auto_expand;
	char encoding_rules;
	boolean align;
	AsnContext context;
} AsnBuffer;


// Memory Management

#define ASN_ALLOC(nitem, Type) (Type*) asn_alloc(nitem, sizeof(Type))

/**
 * Allocates a block (nitems * size) bytes and clears it to 0.
 * 
 * Override this function to provide your own allocation function.
 */
extern void* asn_alloc(size_t nitems, size_t size);

/**
 * Deallocates a memory block allocated by a previous call to asn_alloc().
 * 
 * Override this function to provide your own deallocation function.
 */
extern void asn_free(void* block);

/**
 * Copies a block of n bytes from src to dest.
 * 
 * Override this function to provide your own memory copy function.
 */
extern void* asn_memcpy(void* dest, const void* src, size_t n);

/**
 * Compares the first n bytes of the blocks s1 and s2 as unsigned chars.
 * 
 * Override this function to provide your own memory compare function.
 */
extern int asn_memcmp(const void* s1, const void* s2, size_t n);

/**
 * Performs a binary search for the value key in a table (array) of nelem elements in memory.
 * Parameters:
 * 		key - The item to be searched for (the search key)
 *		base - The base (0th element) of the search table
 *		nelem - The number of entries in the table
 *		width - The number of bytes in each entry
 *		fcmp - A user-defined comparison routine that compares two items and returns a value based on the comparison
 * Return: The address of the first entry in the table that matches the search key on success; 0 (No match) on failure.
 * 
 * Override this function to provide your own bsearch function.
 */
extern void* asn_bsearch(const void* key, const void* base, size_t nelem, size_t width, int (*fcmp)(const void*, const void*));


// I/O Manipulation

/** 
 * Callback routine: Reads up to <code>len</code> bytes of data from the input stream into
 * an array of bytes.  An attempt is made to read as many as <code>len</code> bytes, but a
 * smaller number may be read. The number of bytes actually read is returned as an integer.
 *
 * @param    in     the input stream from which to read data.
 * @param    buf    the buffer into which the data is read.
 * @param    len    the maximum number of bytes to read.
 * @return 
 * 			 the total number of bytes read into the buffer, or
 * 			 <code>-1</code> if there is no more data because the end of
 * 			 the stream has been reached.
 **/
typedef int (*AsnReadBytes)(struct AsnInputStream* in, char* buf, int len);

/** 
 * Callback routine: Writes <code>len</code> bytes from the specified byte array
 * to this output stream.
 * @param    buf   the data.
 * @param    len   the number of bytes to write.
 * @return
 * 			 the total number of bytes written, -1 on failure
 **/
typedef int (*AsnWriteBytes)(struct AsnOutputStream* out, char* buf, int len);

/**
 * Flushes this output stream and forces any buffered output bytes
 * to be written out.
 **/
typedef void (*AsnFlushStream)(struct AsnOutputStream* out);

/* The input stream */
typedef struct AsnInputStream {
	void* fd;	/* file descriptor  */
	AsnReadBytes read;
} AsnInputStream;

/* The output stream */
typedef struct AsnOutputStream {
	void* fd;	/* file descriptor  */
	AsnWriteBytes write;
	AsnFlushStream flush;
} AsnOutputStream;

struct AsnPrinter;

/** 
 * Call Back routine: print anything
 **/
typedef int (*AsnPrint)(struct AsnPrinter* printer, const char *__format, ...);

/* the printer */
typedef struct AsnPrinter {
	void* fd;	 		/* file descriptor  */
	AsnPrint print;	 	/* the print call back  */
	AsnContext context; /* reserved for internal use  */
} AsnPrinter;

// Buffer Allocation

/**
 * Wraps an array into a buffer.
 * 
 * The new buffer will be backed by the given byte array;
 * that is, modifications to the buffer will cause the array to be modified and vice versa.  
 * For Basic Encoding Rules, the new buffer's capacity and limit will be <tt>numBytes</tt>, 
 * and for Pack Encoding Rules, the new buffer's capacity and limit will be <tt>numBytes*8</tt>.
 */
AsnBuffer* wrap_buffer(char* array, unsigned long numBytes, char encodingRules);

/**
 * Allocates a new buffer.
 *
 * For Basic Encoding Rules, the new buffer's capacity and limit will be <tt>numBytes</tt>,
 * and for Pack Encoding Rules, the new buffer's capacity and limit will be <tt>numBytes*8</tt>.
 */
AsnBuffer* alloc_buffer(unsigned long numBytes, boolean autoExpand, char encodingRules);

/**
 * Create a new buffer with the specific underlying input stream
 **/
AsnBuffer* input_stream_buffer(AsnInputStream* in, unsigned long numBytes, char encodingRules);

/**
 * Create a new buffer with the specific underlying output stream
 **/
AsnBuffer* output_stream_buffer(AsnOutputStream* out, unsigned long numBytes, char encodingRules);

/**
 * Free a buffer. The memory of byte array and the buffer itself will 
 * be freed. 
 * 
 * Caution: if this buffer is create by wrap_buffer(), it must be deallocated by
 * calling asn_free() instead of this routine.
 */
void free_buffer(AsnBuffer* buffer);

// Encoding/Decoding Routines

/** 
 * encode the object with encoding rules specified in the buffer 
 **/
int encode_object(AsnBuffer* buffer, void* object, const AsnType* type);

/** 
 * decode the object with encoding rules specified in the buffer 
 **/
int decode_object(AsnBuffer* buffer, void* object, const AsnType* type);


// Freeing Routines

/** 
 * free the object content (memory allocated dynamically) 
 **/
void free_object(void* object, const AsnType* type);


// Printing Routines

/** 
 * print the object content with printer call back
 **/
void print_object(void* object, const AsnType* type, AsnPrinter* printer);


// Error Handling

/* error codes */
#define		INVALID_TAG                     1
#define		INVALID_LENGTH                  2
#define		INVALID_INTEGER                 3
#define		INVALID_ENUM                    4
#define		INVALID_REAL                    5
#define		OUT_OF_MEMORY                   6
#define		INVALID_TIME                    7
#define		MISSING_COMPONENT               8
#define		EXTRA_COMPONENT                 9
#define		INVALID_INDEX                   10
#define		BUFFER_OVERFLOW                 11
#define		BUFFER_UNDERFLOW                12
#define		INVALID_ENCODE_RULE             13
#define		NULL_POINTER_EXCEPTION          14
#define		NOT_PERMITTED_ALPHABET          15
#define		NO_MATCH_INFO_OBJ               16
#define		INVALID_LICENSE                 17
#define		INVALID_SIZE                    18
#define		IO_EXCEPTION                    19
#define		UNSUPPORT_FUNCTION              20

/**
 * print the object content with problem marks
 **/
void print_problem_marks(AsnBuffer* buffer, void* object, const AsnType* type, AsnPrinter* printer);



// ~~ Internal API ~~ //

#define PUBLIC

#ifndef offsetof
#define	offsetof(s, m) (size_t)&( ((s*)0)->m )
#endif

#ifndef msizeof
#define msizeof(s,m) sizeof(((s*)0)->m)
#endif

#ifndef psizeof
#define psizeof(s,m) sizeof(*(((s*)0)->m))
#endif

extern const unsigned char FIRST_MASK[];
extern const unsigned char SECOND_MASK[];
extern const unsigned char SET_MASK[];
extern const unsigned char CLEAR_MASK[];
extern const char* err_msgs[];
extern const char _NUMERIC_STRING_PERMITTED_ALPHABETS_[];

/* license */
extern char sn_key[];
extern int sn_len;

/* metadata types */

typedef struct {
	xlong bmin;
	xlong bmax;
	unsigned int order      :2;
	unsigned int hasBmin    :1;
	unsigned int hasBmax    :1;
	unsigned int numBits    :7;
	unsigned int numOcts    :4;
	unsigned int numBytes   :4;
	unsigned int extensible :1;
} AsnInteger;

typedef struct {
	BigInteger bmin;
	BigInteger bmax;
	unsigned int order      :2;
	unsigned int hasBmin    :1;
	unsigned int hasBmax    :1;
	unsigned int numBits    :(BI_BITS+3+1);
	unsigned int numOcts    :(BI_BITS+3+1)-3;
	unsigned int numBytes   :(BI_BITS+3+1)-3;
	unsigned int extensible :1;
} AsnBigInteger;

typedef struct {
	unsigned int lmin; 
	unsigned int lmax; 
	unsigned int order      :2;
	unsigned int hasLmin    :1;
	unsigned int hasLmax    :1;
	unsigned int numBits    :7;
	unsigned int numOcts    :4;
	unsigned int extensible :1;
} AsnSizeRange;

typedef struct {
	const char* permittedAlphabets;
	unsigned int n;
	unsigned int b :6;
	unsigned int B :6;
	unsigned int reindexing :1; 
	unsigned int REINDEXING :1; 
	AsnSizeRange sizeRange;
} AsnMString;

typedef struct {
	const wchar* permittedAlphabets;
	unsigned int n;
	unsigned int b :6;
	unsigned int B :6;
	unsigned int reindexing :1; 
	unsigned int REINDEXING :1; 
	AsnSizeRange sizeRange;
} AsnWString;

typedef struct {
	const uchar* permittedAlphabets;
	unsigned int n;
	unsigned int b :6;
	unsigned int B :6;
	unsigned int reindexing :1; 
	unsigned int REINDEXING :1; 
	AsnSizeRange sizeRange;
} AsnUString;

typedef struct {
	const AsnType* componentType;
	unsigned int componentWidth;
	AsnSizeRange sizeRange;
} AsnListType;

typedef struct {
	unsigned long tag;
	const AsnType* underlyingType;
} AsnTaggedType;

typedef struct {
	const char** enumNames;
	const int* enumValues;
	unsigned int numEnums :16;
	unsigned int numExtensions :16;
	unsigned int numBits :7;
	unsigned int numOcts :4;
	unsigned int extensible :1;
	unsigned int width :4;
} AsnEnumerated;

typedef struct {
	const char* name;
	const AsnType* type;
	unsigned int width :15;
	unsigned int cycle :1;
} AsnAlternative;

typedef struct {
	const AsnAlternative* alternatives;
	unsigned int numAlternatives: 16;
	unsigned int numExtensions :16;
	unsigned int numBits :10;
	unsigned int numOcts :7;
	unsigned int numBytes :7;
	unsigned int extensible :1; 
	unsigned int valueOffset :7;
} AsnChoice;

typedef struct {
	const char* name;
	const AsnType* type;
	const void* defval;
	unsigned int optional:1;
	unsigned int offset :16;
	unsigned int width :15;
} AsnComponent;

typedef struct {
	const AsnComponent* components;
	unsigned int numComponents :16;
	unsigned int bitmapSize :16;
} AsnExtensionAddition;

typedef struct {
	const AsnComponent* rootComponents;
	const AsnExtensionAddition* extensionAdditions;
	unsigned int numComponents: 16;
	unsigned int numExtensions: 16;
	unsigned int bitmapSize	:15;
	unsigned int extensible :1;
} AsnComposite;

typedef struct {
	unsigned int fieldOffset;
	unsigned int compomentIndex;
	unsigned int compomentLevel;
} AsnInfoObjIndexer;

typedef struct {
	unsigned int numInfoObjs :13;
	unsigned int widthOfInfoObj: 8;
	unsigned int actualTypeOffset: 8;
	unsigned int numIndexers :3;
	const void* infoObjects;
	const AsnInfoObjIndexer* indexers;
	const AsnType* actualType; // exclusive with other fields
} AsnOpenType;

extern const char _NUMERIC_STRING_pa_[];

extern const AsnType BOOLEAN_TYPE;

extern const AsnType NULL_TYPE;

#define INT_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &INT_CODEC, &_##name##_cfg_  }

#define UINT_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &UINT_CODEC, &_##name##_cfg_  }

#define LONG_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &LONG_CODEC, &_##name##_cfg_  }

#define ULONG_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &ULONG_CODEC, &_##name##_cfg_  }

#define XLONG_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &XLONG_CODEC, &_##name##_cfg_  }

#define UXLONG_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &UXLONG_CODEC, &_##name##_cfg_  }

#define BIGINTEGER_TYPE(name, bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible)\
	const AsnBigInteger _##name##_cfg_ = { bmin, bmax, order, hasBmin, hasBmax, numBits, numOcts, numBytes, extensible };\
	const AsnType name = { &BIGINTEGER_CODEC, &_##name##_cfg_  }

extern const AsnType FLOAT_TYPE;

extern const AsnType DOUBLE_TYPE;

#define BITSTRING_TYPE(name, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnSizeRange _##name##_cfg_ = {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible};\
	const AsnType name = { &BITSTRING_CODEC, &_##name##_cfg_  }

#define OCTETSTRING_TYPE(name, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnSizeRange _##name##_cfg_ = {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible};\
	const AsnType name = { &OCTETSTRING_CODEC, &_##name##_cfg_  }

extern const AsnType OBJECTIDENTIFIER_TYPE;

extern const AsnType RELATIVEOID_TYPE;

#define NUMERICSTRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnMString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &NUMERICSTRING_CODEC, &_##name##_cfg_  }
	
#define PRINTABLESTRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnMString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &PRINTABLESTRING_CODEC, &_##name##_cfg_  }
	
#define VISIBLESTRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnMString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &VISIBLESTRING_CODEC, &_##name##_cfg_  }
	
#define IA5STRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnMString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &IA5STRING_CODEC, &_##name##_cfg_  }

#define BMPSTRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnWString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &BMPSTRING_CODEC, &_##name##_cfg_  }
	
#define UNIVERSALSTRING_TYPE(name, pa, n, b, B, reindexing, REINDEXING, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnUString _##name##_cfg_ = { pa, n, b, B, reindexing, REINDEXING, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &UNIVERSALSTRING_CODEC, _&name##_cfg_  }

extern const AsnType TELETEXSTRING_TYPE;

extern const AsnType VIDEOTEXSTRING_TYPE;

extern const AsnType GRAPHICSTRING_TYPE;

extern const AsnType GENERALSTRING_TYPE;

extern const AsnType CHARACTERSTRING_TYPE;

extern const AsnType UTF8STRING_TYPE;

extern const AsnType OBJECTDESCRIPTOR_TYPE;

extern const AsnType GENERALIZEDTIME_TYPE;

extern const AsnType UTCTIME_TYPE;

#define SEQUENCEOF_TYPE(name, componentType, componentWidth, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnListType _##name##_cfg_ = { &componentType, componentWidth, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &SEQUENCEOF_CODEC, &_##name##_cfg_ }

#define SETOF_TYPE(name, componentType, componentWidth, lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible)\
	const AsnListType _##name##_cfg_ = { &componentType, componentWidth, {lmin, lmax, order, hasLmin, hasLmax, numBits, numOcts, extensible} };\
	const AsnType name = { &SETOF_CODEC, &_##name##_cfg_ }

#define IMPLICIT_TYPE(name, tag, underlyingType)\
	const AsnTaggedType _##name##_cfg_ = {  tag, &underlyingType };\
	const AsnType name = { &IMPLICIT_CODEC, &_##name##_cfg_ }

#define EXPLICIT_TYPE(name, tag, underlyingType)\
	const AsnTaggedType _##name##_cfg_ = {  tag, &underlyingType };\
	const AsnType name = { &EXPLICIT_CODEC, &_##name##_cfg_ }
	
#define OPEN_TYPE(name, infoObjects, numInfoObjs, widthOfInfoObj, actualTypeOffset, indexers, numIndexers, actualType)\
	const AsnOpenType _##name##_cfg_ = {  numInfoObjs, widthOfInfoObj, actualTypeOffset, numIndexers, infoObjects, indexers, actualType };\
	const AsnType name = { &OPEN_CODEC, &_##name##_cfg_ }
	
#define DEFAULT_VALUE(name, length, bytes)\
	const Octets name = { length, bytes }
	
/* ASN.1 Codec */

extern const struct AsnCodec BOOLEAN_CODEC;

extern const struct AsnCodec NULL_CODEC;

extern const struct AsnCodec INT_CODEC;

extern const struct AsnCodec UINT_CODEC;

extern const struct AsnCodec LONG_CODEC;

extern const struct AsnCodec ULONG_CODEC;

extern const struct AsnCodec XLONG_CODEC;

extern const struct AsnCodec UXLONG_CODEC;

extern const struct AsnCodec BIGINTEGER_CODEC;

extern const struct AsnCodec ENUMERATED_CODEC;

extern const struct AsnCodec FLOAT_CODEC;

extern const struct AsnCodec DOUBLE_CODEC;

extern const struct AsnCodec BITSTRING_CODEC;

extern const struct AsnCodec OCTETSTRING_CODEC;

extern const struct AsnCodec OBJECTIDENTIFIER_CODEC;

extern const struct AsnCodec RELATIVEOID_CODEC;

extern const struct AsnCodec NUMERICSTRING_CODEC;

extern const struct AsnCodec PRINTABLESTRING_CODEC;

extern const struct AsnCodec VISIBLESTRING_CODEC;

extern const struct AsnCodec IA5STRING_CODEC;

extern const struct AsnCodec BMPSTRING_CODEC;

extern const struct AsnCodec UNIVERSALSTRING_CODEC;

extern const struct AsnCodec TELETEXSTRING_CODEC;

extern const struct AsnCodec VIDEOTEXSTRING_CODEC;

extern const struct AsnCodec GRAPHICSTRING_CODEC;

extern const struct AsnCodec GENERALSTRING_CODEC;

extern const struct AsnCodec CHARACTERSTRING_CODEC;

extern const struct AsnCodec UTF8STRING_CODEC;

extern const struct AsnCodec OBJECTDESCRIPTOR_CODEC;

extern const struct AsnCodec GENERALIZEDTIME_CODEC;

extern const struct AsnCodec UTCTIME_CODEC;

extern const struct AsnCodec SEQUENCE_CODEC;

extern const struct AsnCodec SET_CODEC;

extern const struct AsnCodec CHOICE_CODEC;

extern const struct AsnCodec SEQUENCEOF_CODEC;

extern const struct AsnCodec SETOF_CODEC;

extern const struct AsnCodec IMPLICIT_CODEC;

extern const struct AsnCodec EXPLICIT_CODEC;

extern const struct AsnCodec OPEN_CODEC;

#ifdef __cplusplus
}
#endif

#endif /*ASNRT_H_*/

